Skip to main content

type system

Primitive & Objects

Ysharp is a dynamic typed language with support of optional type tags attributes. Type system works like Type Script but it checks type compatibility in runtime instead of compile time.

In Ysharp, every variable is NOT derived from object type. There are primitives and object types.

There are 5 primitive types in Ysharp

  • int
  • double
  • char
  • bool
  • null

There are 3 object types in Ysharp

  • function
  • class
  • string

Note
Strings are categorized under object but parser has built in support for creating strings so you can use shorthand for creating string just like primitive types. I believe using string as primitive is more natural to most of the programmers so i added this feature.

For example :

var f_name = "yagiz"; // shorthand for creating string
var l_name = new String("erdem"); // explicit object syntax
println f_name + " " + l_name; // yagiz erdem

Under string section you can access full api documentation .

Naming Conventions

Always use the same coding conventions for all your Ysharp projects.

Coding conventions are style guidelines for programming. They typically cover:

  • Naming and declaration rules for variables and functions.
  • Rules for the use of white space, indentation, and comments.
  • Programming practices and principles.

Coding conventions secure quality:

  • Improve code readability
  • Make code maintenance easier

Coding conventions can be documented rules for teams to follow, or just be your individual coding practice.

Always use the same naming convention for all your code. For example:

  • Variable and function names written as camelCase
  • Global variables written in UPPERCASE (We don't, but it's quite common)
  • Constants (like PI) written in UPPERCASE

Underscores:
Many programmers prefer to use underscores (date_of_birth), especially in SQL databases. Underscores are often used in PHP documentation.

PascalCase:
PascalCase is often preferred by C programmers.

camelCase:
camelCase is used by Ysharp itself.

Note
All characters in identifier must be alfa-numeric and identifier cannot start with numeric character .

For example:

var 1a = 40; // Syntax error
var a1 = 40; // OK
var _a = 40; // OK variables can start with underscore

Primitives

In Ysharp, a primitive (primitive value, primitive data type) is data that is not an object and has no methods or properties. Most of the time, a primitive value is represented directly at the lowest level of the language implementation.

All primitives are immutable, they cannot be altered. It is important not to confuse a primitive itself with a variable assigned a primitive value. The variable may be reassigned to a new value, but the existing value can not be changed in the ways that objects, arrays, and functions can be altered. The language does not offer utilities to mutate primitive values.

// int
var age = 21;
println age; // 21

// double
var pi = 3.14;
println pi; // 3.14

// char
var letter = 'A';
println letter; // A

// bool
var isActive = true;
println isActive; // true

// null
var data = null;
println data; // null

Objects

Objects are runtime structures that has prototype, instance/object level method/properties. Objects are specialized under 3 categories which are strings, functions, classes.

Functions & Classes

In Ysharp, functions and classes are categorized into subtypes based on how they are defined and used.

Function Types

Ysharp supports three types of functions:

  • User defined functions
    Functions declared by the user using the function keyword.

  • Lambda expressions
    Anonymous functions that can be defined inline. They are similar to lambda (arrow) functions in JavaScript.

  • Native functions
    Built in functions provided by the Ysharp runtime and standard library.

Class Types

Ysharp supports two types of classes:

  • User defined classes
    Classes created by the user using the class keyword.

  • Native classes
    Built in classes provided by the Ysharp runtime and standard library.

You can visit class, function and string api documentation to get more details, theese topics are very deep and i dont want to go over every single api in this section.

Type tags

Type tags adds syntax on top of Ysharp expressions, allowing developers to add types.

Unlike statically typed languages, Ysharp does not enforce types at compile time.
Instead, type tags are checked at runtime to ensure that assigned values are compatible.

Type tags are used to:

  • Improve code readability
  • Catch type errors early (at runtime)
  • Document developer intent
  • Add lightweight type safety without losing flexibility

Syntax

Type tags are declared after variable or parameter names:

var x : int = 10;
var name : string = "yagiz";
var flag : bool = true;

If no type is provided, default is any. Programmer do not have to write any. Any type matches with all value types .

var x : any = 10;

Supported Type Tags

Primitive Types

  • int
  • double
  • number (accepts both int and double)
  • char
  • bool

Special Types

any → accepts all values function string

Custom Types

User defined class names can also be used:

class Person {}

var p : Person = new Person(); // OK

Runtime Type Checking

Type checking happens during assignment:

var x : int = 10;
x = 20; // OK
x = "text"; // ERROR

Null Behavior

null is allowed for all types:

var x : int = null;     // OK
var name : string = null; // OK

Type Compatibility

var x : number = 10;     // OK (int → number)
var y : number = 3.14; // OK (double → number)

var z : int = 3.14; // ERROR

Function Parameters

Type tags can be used in function parameters:

function add(a : int, b : int) do
return a + b;
end

add(10, 20); // OK
add(10, "x"); // ERROR

Return Types

function square(x : int) : int do
return x * x;
end

var a : int = square(4); // 16 OK
var b : string = square(4) // ERROR
// function cannot return string since it has int type taf for return

function test() : int do
return "string";
end

test();

Class Fields

Type tags can be used in class properties:

class User {
var name : string;
var age : int;
}

Type Tags vs Dynamic Typing

Ysharp remains fully dynamic, even with type tags:

  • Types are optional
  • Types are enforced only at runtime
  • No compile time type system exists

Best Practices

  • Use any only when necessary
  • Prefer number over int/double if flexibility is needed
  • Use type tags in public APIs (functions, classes)
  • Avoid over typing internal temporary variables

Type Api

There is a separate api for making type checks and type conversions.

Type Class

Static Methods

MethodSignatureReturn TypeDescription
getTypeType.getType(value)stringReturns the type name of the given value (e.g. "number", "string", "array")
getTypeTagType.getTypeTag(value)stringReturns the user-defined or environment-specific type tag associated with the given value
isBoolisBool(value: any)boolReturns true if the given value is of type boolean
isCharisChar(value: any)boolReturns true if the given value is of type char
isClassisClass(value: any)boolReturns true if the given value is of type class
isClassInstanceisClassInstance(value: any)boolReturns true if the given value is a class instance
isDoubleisDouble(value: any)boolReturns true if the given value is of type double
isFunctionisFunction(value: any)boolReturns true if the given value is a function or callable
isIntisInt(value: any)boolReturns true if the given value is of type integer
isNativeObjectisNativeObject(value: any)boolReturns true if the given value is a native (Java-backed) object
isStringisString(value: any)boolReturns true if the given value is of type string

Static Class

ClassConstructor SignatureTypeDescription
Type.Converterno signature - static class_Converter_ <class:Converter>Converter class used for data conversions

Converter Class

Static Methods

MethodSignatureReturn TypeDescription
constructorType.Converter()-Static class, cannot be instantiated
toStringType.Converter.toString(v : any)stringConverts given value to string
toIntType.Converter.toInt(v : any)intConverts given value to integer
toDoubleType.Converter.toDouble(v : any)doubleConverts given value to double
toCharType.Converter.toChar(v : any)charConverts given value to char
toBoolType.Converter.toBool(v : any)boolConverts given value to boolean
toNativeObjectType.Converter.toNativeObject(v : any)anyConverts value to native (Java-backed) object

Examples

var a = 10;
var b = 10.5;
var c = "hello";
var d = true;

println(Type.isInt(a)); // true
println(Type.isDouble(b)); // true
println(Type.isString(c)); // true
println(Type.isBool(d)); // true
class User {
var name;
constructor(name) do
this.name = name;
end
}

var u = new User("yağız");

println(Type.isClass(User)); // true
println(Type.isClassInstance(u)); // true
println(Type.isClassInstance(User)); // false
function add(a, b) do
return a + b;
end

var x = 5;

println(Type.isFunction(add)); // true
println(Type.isFunction(x)); // false
var a : number = 10;

println Type.getType(a); // int
println Type.getTypeTag(a); // number
var arr = [1, 2, 3];

println(Type.isNativeObject(arr.toNativeArray)); // true
println(Type.isNativeObject(Type.Converter.toNativeObject(arr))); // true
println(Type.isNativeObject(arr)); // true
var x = "123";

var n = Type.Converter.toInt(x);
println(n + 1); // 124

var d = Type.Converter.toDouble("3.14");
println(d * 2); // 6.28

var s = Type.Converter.toString(999);
println(s); // "999"
var x = "abc";

var n = Type.Converter.toInt(x); // throws error
function process(value) do
if Type.isInt(value) then do
return value * 2;
end

if Type.isString(value) then do
return value + "!";
end

return null;
end

println(process(10)); // 20
println(process("test")); // "test!"